home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS26.ADF / SoundScape / LatticeExamples / movie.c < prev    next >
C/C++ Source or Header  |  1989-01-26  |  13KB  |  379 lines

  1. /*      MOVIE.C        Animation Queue Sheet generator 
  2.  
  3.         (c) 1986 Todor Fay 
  4.  
  5.         This program takes a composed track and computes a score chart 
  6.         for the first 16 tracks, with events marked every frame. 
  7.     Link this with lib/sslink.obj.
  8. */ 
  9.  
  10. #include "exec/types.h" 
  11. #include "exec/exec.h" 
  12. #include "libraries/dos.h" 
  13. #include "intuition/intuition.h" 
  14. #include "soundscape.h" 
  15. #include "modules/tapedeck.h" 
  16.  
  17. /*      This program installs itself in the SoundScape environment, 
  18.         so it needs to have an icon.  The following data describes 
  19.         an image of a short piece of film: 
  20. */ 
  21.  
  22. UWORD filmdata[] = {        /* 36 x 17 */ 
  23. 0,        0,        0,         
  24. 14844,        15985,        49152,         
  25. 392,        7800,        0,         
  26. 377,        15960,        0,         
  27. 14655,        65273,        49152,         
  28. 303,        65272,        0,         
  29. 0,        0,        0,         
  30. 14844,        15993,        49152,         
  31. 392,        7792,        0,         
  32. 377,        15992,        0,         
  33. 14655,        65241,        49152,         
  34. 303,        65272,        0,         
  35. 0,        0,        0,         
  36. 14844,        15993,        49152,         
  37. 392,        7800,        0,         
  38. 377,        15984,        0,         
  39. 14655,        65273,        49152,         
  40. 65535,        65535,        61440,         
  41. 50688,        646,        12288,         
  42. 65136,        663,        61440,         
  43. 65167,        62119,        61440,         
  44. 50703,        45574,        12288,         
  45. 65031,        49671,        63488,         
  46. 65535,        65535,        64512,         
  47. 50688,        646,        15360,         
  48. 65136,        647,        64512,         
  49. 65167,        62103,        64512,         
  50. 50703,        12838,        14336,         
  51. 65031,        49671,        61440,         
  52. 65535,        65535,        61440,         
  53. 50688,        646,        12288,         
  54. 65136,        647,        61440,         
  55. 65167,        62087,        61440,         
  56. 50703,        29206,        12288,         
  57. }; 
  58.  
  59. struct Image filmimage =  
  60.     {  0,0,36,17,2,&filmdata[0],3,0,0,        }; 
  61.  
  62. struct IntuiText filmtext[] = { 
  63.     {  2,0,JAM2,-32,0,0,"CPS",0        }, 
  64.     {  2,0,JAM2,-48,0,0,"Start",0        }, 
  65.     {  2,0,JAM2,-48,0,0,"Count",0        }, 
  66.     {  3,0,JAM2,0,20,0,"Do it",0        }, 
  67. }; 
  68.  
  69. struct StringInfo filminfo[] = { 
  70.     {  "60\0   ",0,0,6,0,0,0,0,0,0,0,0,0,        }, 
  71.     {  "0\0    ",0,0,6,0,0,0,0,0,0,0,0,0,        }, 
  72.     {  "1\0    ",0,0,6,0,0,0,0,0,0,0,0,0,        }, 
  73. }; 
  74.  
  75. short box[] = { 0,0,52,0,52,10,0,10,0,0 }; 
  76.  
  77. struct Border gadgetborder = { -2,-2,3,0,JAM2,5,&box[0],0 }; 
  78.  
  79. struct Gadget filmgadgets[] = { 
  80.     {   0,60,15,48,8, 
  81.         GADGHCOMP,GADGIMMEDIATE | RELVERIFY | LONGINT, STRGADGET, 
  82.         &gadgetborder,0,&filmtext[0],0,&filminfo[0],0,0,  }, 
  83.     {   &filmgadgets[0],60,25,48,8, 
  84.         GADGHCOMP,GADGIMMEDIATE | RELVERIFY | LONGINT, STRGADGET, 
  85.         &gadgetborder,0,&filmtext[1],0,&filminfo[1],1,0,  }, 
  86.     {   &filmgadgets[1],60,35,48,8, 
  87.         GADGHCOMP,GADGIMMEDIATE | RELVERIFY | LONGINT, STRGADGET, 
  88.         &gadgetborder,0,&filmtext[2],0,&filminfo[2],2,0,  }, 
  89.     {   &filmgadgets[2],120,15,36,30, 
  90.         GADGHCOMP | GADGIMAGE,GADGIMMEDIATE | RELVERIFY, BOOLGADGET, 
  91.         &filmimage,0,&filmtext[3],0,0,3,0,  }, 
  92. }; 
  93.  
  94. struct NewWindow filmwindow = { 
  95.         0,0,190,50,2,1,GADGETUP | CLOSEWINDOW, 
  96.         WINDOWCLOSE | WINDOWDRAG | ACTIVATE | WINDOWDEPTH | SMART_REFRESH | WINDOWSIZING, 
  97.         &filmgadgets[3],0," Film Score ",0,0,40,20,0,0,WBENCHSCREEN 
  98. }; 
  99.  
  100. static char outbuff[100]; 
  101. char printit = 0; 
  102.  
  103. linedone() 
  104.  
  105. /*      When a line is ready to print, run through it and strip out all 
  106.         the nulls that were generated by the integer to character conversions. 
  107.         Then, put a null back after the last number, so only this much of the 
  108.         line will be printed. 
  109. */ 
  110.  
  111.     short i; 
  112.     short last = 0; 
  113.     for (i=0; i<80; i++) { 
  114.         if (!outbuff[i]) { 
  115.             outbuff[i] = ' '; 
  116.             last = i; 
  117.         } 
  118.     } 
  119.     outbuff[last] = 0; 
  120.  
  121. newline(time) 
  122.  
  123. /*      Prepare the buffer for a new line by clearing it and putting 
  124.         the time in seconds and frames at the start of it. 
  125.         'stcu_d' is the Lattice decimal integer to ascii routine. 
  126. */ 
  127.  
  128. long time; 
  129.  
  130.     short i; 
  131.     setmem(outbuff,80,' '); 
  132.     stcu_d(outbuff,(time / 24),10); 
  133.     i = strlen(outbuff); 
  134.     outbuff[i] = ':'; 
  135.     stcu_d(&outbuff[i + 2],(time % 24),10); 
  136.  
  137. outcode(note) 
  138.  
  139. /*      This routine is called by SoundScape whenver there is a note for 
  140.         this device.   
  141.         We want to take the note and stick its value in outbuff, positioned 
  142.         by the MIDI channel.   
  143.         If note off event (the velocity is 0), ignore it. 
  144. */ 
  145.  
  146. struct Note *note; 
  147.  
  148.     short channel = note->status & 0x0F; 
  149.     unsigned char stat = note->status & 0xF0; 
  150.     if (note->velocity) { 
  151.         stcu_d(&outbuff[(channel * 4) + 10],note->value,4); 
  152.     } 
  153.     FreeNode(note);         /* Return the note to SoundScape. */ 
  154. }    
  155.  
  156. opencode(direction) 
  157.  
  158. /*      You must provide code for SoundScape to open your port (AddMidiPort 
  159.         installs it, but doesn`t activate it.) 
  160.         Each port handles both input and output, or one or the other. 
  161.         Direction says which one to open. 
  162.         In this case, we don't have anything to do, just return TRUE. 
  163.         An example where opencode would do something would be if your 
  164.         output port involved a display window.  Opencode(0) would instruct 
  165.         you to open that window.  Closecode(0) would instruct you to close 
  166.         it.         
  167. */ 
  168.  
  169. char direction; 
  170.  
  171.     return(1); 
  172.  
  173. closecode(direction) 
  174.  
  175. char direction; 
  176.  
  177.     return(1); 
  178.  
  179. editcode(direction,command,buffer) 
  180.  
  181. /*      We aren't providing any of the edit options.  However, should somebody 
  182.         wish to edit the state, let them know the size is 0. 
  183. */ 
  184.  
  185. char direction, command; 
  186. long buffer[]; 
  187.  
  188.     buffer[0] = 0; 
  189.     return(0); 
  190.  
  191. long SoundScapeBase, IntuitionBase; 
  192.  
  193. main() { 
  194.     long time = 0; 
  195.     short linecount = 0; 
  196.     long frames = 0; 
  197.     long oldframes = 0; 
  198.     long startpoint = 0; 
  199.     long stoppoint = 24; 
  200.     long framesleft; 
  201.     long clockspersecond = 60; 
  202.     short page; 
  203.     long file; 
  204.     char filename[40]; 
  205.     char pagestring[10]; 
  206.     struct Window *window; 
  207.     static char tracktop[] = "\n\nTime      <----------------------- Tracks ----------------------------->\n"; 
  208.     static char pagetop[] = "Sec:Frame 1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16\n\n"; 
  209.     static char tabs[] = "\t\t\t\t    page "; 
  210.     char carriagereturn = '\n'; 
  211.     char formfeed = 12; 
  212.     struct IntuiMessage *message; 
  213.     struct Note *note; 
  214.     struct Track *track; 
  215.     struct TapeState ts; 
  216.     short i; 
  217.     short thisport; 
  218.     struct Gadget *gadget; 
  219.     IntuitionBase = OpenLibrary("intuition.library",0); 
  220.     SoundScapeBase = OpenLibrary("soundscape.library",0); 
  221.     if (!SoundScapeBase) { 
  222.         CloseLibrary(IntuitionBase); 
  223.         return; 
  224.     } 
  225.     window = OpenWindow(&filmwindow); 
  226.     if (!window) { 
  227.         CloseLibrary(IntuitionBase); 
  228.         CloseLibrary(SoundScapeBase); 
  229.         return; 
  230.     } 
  231. /*      Add this port to the system.  We specify a desired port id of -1, 
  232.         in other words any port.  */ 
  233.     thisport = AddMidiPort(opencode,closecode,editcode,outcode, 
  234.         &filmimage,&filmimage,-1,"Animator's Helper"); 
  235. /*      Open this port.  Though our opencode does nothing, SoundScape will. */ 
  236.     OpenMidiPort(thisport,0); 
  237.     OpenMidiPort(thisport,1); 
  238. /*      Open the tape deck. */ 
  239.     OpenMidiPort(6,0); 
  240.     filename[0] = 0; 
  241.     for(;;) { 
  242.         while (message = (struct IntuiMessage *) GetMsg(window->UserPort))  
  243.             ReplyMsg(message); 
  244.         while (!(message = (struct IntuiMessage *) GetMsg(window->UserPort))) 
  245.             WaitPort(window->UserPort); 
  246.         if (message->Class == CLOSEWINDOW) break; 
  247.         gadget = message->IAddress; 
  248.         ReplyMsg(message); 
  249.         switch (gadget->GadgetID) { 
  250.             case 0 : 
  251.                 clockspersecond = filminfo[0].LongInt; 
  252.                 break; 
  253.             case 1 : 
  254.                 startpoint = (filminfo[1].LongInt * 24); 
  255.                 break; 
  256.             case 2 : 
  257.                 stoppoint = (filminfo[2].LongInt * 24); 
  258.                 break; 
  259.             case 3 :                /* Do it. */ 
  260.                 time = (startpoint * clockspersecond) / 24; 
  261. /*      Get the tape deck state. */ 
  262.                 EditMidiPort(6,0,2,&ts); 
  263. /*      Release the tracks. */ 
  264.                 FreeTree(ts.toptrack); 
  265. /*      Set them to 0. */ 
  266.                 ts.toptrack = ts.activetrack = 0; 
  267.                 ts.trackname[0] = 0; 
  268.                 EditMidiPort(6,0,3,&ts); 
  269. /*      Read in a new set of tracks (the song). */ 
  270.                 ts.toptrack = ts.activetrack = ReadList(TRACK,ts.trackname); 
  271. /*      Give the tape deck this song and set the timer and punch points. */ 
  272.                 ts.td_timer = time; 
  273.                 ts.punchin = ts.punchout = 0; 
  274.                 EditMidiPort(6,0,3,&ts); 
  275. /*      If there was no song, leave. */ 
  276.                 if (!ts.toptrack) break; 
  277. /*      Get the name of the file to save to. Template is .film  */ 
  278.                 WriteFileName(filename,"Film File","film"); 
  279. /*      If the user selected QUIT, filename[0] is 0. */ 
  280.                 if (!filename[0]) break; 
  281.                 file = Open(filename,MODE_NEWFILE); 
  282.                 if (!file) break; 
  283. /*      Put in the top of page information. */ 
  284.                 Write(file,ts.trackname,strlen(ts.trackname)); 
  285.                 Write(file,tabs,strlen(tabs)); 
  286.                 page = 1; 
  287.                 stcu_d(pagestring,page,10); 
  288.                 Write(file,pagestring,strlen(pagestring)); 
  289.                 Write(file,tracktop,strlen(tracktop)); 
  290.                 Write(file,pagetop,strlen(pagetop)); 
  291.                 i = 0; 
  292. /*      Set the first 16 tracks to send to this port and each one has  
  293.         its own MIDI channel. */ 
  294.                 for (track = ts.toptrack; i < 16; i++ ) { 
  295.                     if (!track) break; 
  296.                     track->channelout = i; 
  297.                     track->portout = thisport; 
  298.                     track = track->link.next; 
  299.                 } 
  300. /*      Make sure the tape deck is STOPPED (or it won't START.) */ 
  301.                 note = AllocNode(NOTE); 
  302.                 note->status = STOP; 
  303.                 OutMidiPort(6,note); 
  304. /*      Fast forward the tapedeck to where we want to start. */ 
  305.                 note = AllocNode(NOTE); 
  306.                 note->status = SONGPOSITION; 
  307. /*      MIDI Song position is clocks divided by 6. */ 
  308.                 i = time / 6; 
  309.                 note->value = i & 0x7F; 
  310.                 note->velocity = (i >> 7) & 0x7F; 
  311. /*      But internally, SoundScape lets you include the mod 6. */ 
  312.                 note->duration = time % 6; 
  313.                 OutMidiPort(6,note); 
  314. /*      Tell the tapedeck to start playing from this point. */ 
  315.                 note = AllocNode(NOTE); 
  316.                 note->status = CONTINUE; 
  317.                 OutMidiPort(6,note); 
  318.                 frames = startpoint; 
  319.                 framesleft = stoppoint; 
  320.                  oldframes = frames; 
  321.                 newline(frames); 
  322.                 linecount = 0; 
  323.                 while (framesleft) { 
  324.                     oldframes = frames; 
  325.                     frames = (time * 24) / clockspersecond; 
  326. /*      Send a clock pulse.  As soon as it goes out, the tape deck, which runs 
  327.         at a higher priority, will call outcode for each of the notes it is 
  328.         ready to send at this point in time. */ 
  329.                     note = AllocNode(NOTE); 
  330.                     note->status = CLOCK; 
  331.                     OutMidiPort(6,note); 
  332. /*      All events for this MIDI click should be in outbuff now. 
  333.         See if we've done enough to move to a new frame. */ 
  334.                     if (frames != oldframes) { 
  335. /*      New frame.  Print this one, then prepare for the next. */ 
  336.                         framesleft--; 
  337.                         linedone(); 
  338.                         Write(file,outbuff,strlen(outbuff)); 
  339.                         Write(file,&carriagereturn,1); 
  340.                         if (++linecount == 48) { 
  341.                             if (!framesleft) break; 
  342.                             page++; 
  343.                             linecount = 0; 
  344.                             Write(file,&formfeed,1); 
  345.                             Write(file,ts.trackname,strlen(ts.trackname)); 
  346.                             Write(file,tabs,strlen(tabs)); 
  347.                             stcu_d(pagestring,page,10); 
  348.                             Write(file,pagestring,strlen(pagestring)); 
  349.                             Write(file,tracktop,strlen(tracktop)); 
  350.                             Write(file,pagetop,strlen(pagetop)); 
  351.                         } 
  352. /*      Delay so the low priority task that prints the tape deck counter 
  353.         has a chance to do so. */ 
  354.                         Delay(2); 
  355.                         newline(frames); 
  356.                     } 
  357.                     time++; 
  358.                 } 
  359.                 Close(file); 
  360.                 break; 
  361.         } 
  362.     } 
  363.     CloseWindow(window); 
  364.     RemoveMidiPort(thisport); 
  365.     CloseLibrary(SoundScapeBase); 
  366.     CloseLibrary(IntuitionBase); 
  367.